package client;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URI;

public class CLIClient {

	public static void main(String[] args) throws Exception {
		CLIClient cliClient = new CLIClient();
		cliClient.run(args);
	}

	private ClientImpl client;

	public CLIClient() throws Exception {
		client = new ClientImpl();
	}

	private void printErrorMessage() {
		System.out.println("Incorrect command, try to use:");
		System.out.println(" sub   <topic>");
		System.out.println(" unsub <topic>");
		System.out.println(" pub   <topic> <message>");
		System.out
				.println(" multipub   <topic> <period[s]:step[ms]> [<message>]");
		System.out.println(" restart");
		System.out.println(" exit");
	}

	private void run(String[] args) throws Exception {
		if (args.length != 2 && args.length != 3) {
			System.out
					.println("Usage: cliclient <network_interface_name> <broker_manager_ip> [<username>]");
			System.out
					.println(" <network_interface_name> the name of the network interface to use (run ifconfig to view possible choices)");
			System.out
					.println(" <broker_manager_ip>      the ip of of the machine where the broker manager is running");
			System.out
					.println(" <username>      			the human-friendly username associated to this client (not necessairly unique)");
		}

		// Run the client
		if (args.length == 2)
			client.start(args[0], new URI(args[1]), null);
		else
			client.start(args[0], new URI(args[1]), args[2]);

		// Grab input stream
		InputStreamReader inStream = new InputStreamReader(System.in);
		BufferedReader in = new BufferedReader(inStream);
		String cmd = "";
		String[] cmdParts;

		// Cyclically read and execute commands
		while (true) {
			cmd = in.readLine();
			cmdParts = cmd.split(" ");

			// Null commands
			if (cmdParts == null || cmdParts.length == 0 || cmdParts[0] == null) {
				printErrorMessage();
				continue;
			}

			// Subscribe
			else if (cmdParts[0].equals("sub")) {
				if (cmdParts.length != 2) {
					printErrorMessage();
					continue;
				}
				try {
					client.subscribe(cmdParts[1]);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			// Unsubscribe
			else if (cmdParts[0].equals("unsub")) {
				if (cmdParts.length != 2) {
					printErrorMessage();
					continue;
				}
				try {
					client.unsubscribe(cmdParts[1]);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			// Publish
			else if (cmdParts[0].equals("pub")) {
				if (cmdParts.length != 3) {
					printErrorMessage();
					continue;
				}
				try {
					client.publish(cmdParts[2], cmdParts[1]);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			// Multiple publish
			else if (cmdParts[0].equals("multipub")) {
				if (cmdParts.length != 3 && cmdParts.length != 4) {
					printErrorMessage();
					continue;
				}
				String message = "Message";
				if (cmdParts.length == 4) {
					message = cmdParts[3];
				}
				try {
					String[] subParts = cmdParts[2].split(":");
					if (subParts.length != 2) {
						printErrorMessage();
						continue;
					}
					int step = Integer.parseInt(subParts[1]);
					int period = Integer.parseInt(subParts[0]) * 1000;
					for (int time = 0, count = 0; time < period; time += step, count++) {
						client.publish(message + " " + count, cmdParts[1]);
						Thread.sleep(step);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			// Restart
			else if (cmdParts[0].equals("restart")) {
				if (cmdParts.length != 1) {
					printErrorMessage();
					continue;
				}
				try {
					client.stop(false);
					client.start(args[0], new URI(args[1]), args[2]);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}

			// Exit
			else if (cmdParts[0].equals("exit")) {
				if (cmdParts.length != 1) {
					printErrorMessage();
					continue;
				}
				try {
					client.stop(true);
					return;
				} catch (Exception e) {
					e.printStackTrace();
				}
			} else {
				printErrorMessage();
			}
		}
	}
}
